/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package beans;

import dao.ExpensesJpaController;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import javax.persistence.EntityManager;


import javax.persistence.Query;
import pojos.Employees;
import pojos.Expenses;
import pojos.Projects;
import pojos.TimeLog;

/**
 *
 * @author A7med Kotb
 */
public abstract class AbstractFacade<T> {

    private Class<T> entityClass;

    public AbstractFacade(Class<T> entityClass) {
        this.entityClass = entityClass;
    }

    protected abstract EntityManager getEntityManager();

    public void create(T entity) {
        getEntityManager().persist(entity);
    }

    public void edit(T entity) {
        getEntityManager().merge(entity);
    }

    public void remove(T entity) {
        getEntityManager().remove(getEntityManager().merge(entity));
    }

    public T find(Object id) {
        return getEntityManager().find(entityClass, id);
    }

    public List<T> findAll() {
        javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
        cq.select(cq.from(entityClass));
        return getEntityManager().createQuery(cq).getResultList();
    }

    public List<T> findRange(int[] range) {
        javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
        cq.select(cq.from(entityClass));
        javax.persistence.Query q = getEntityManager().createQuery(cq);
        q.setMaxResults(range[1] - range[0]);
        q.setFirstResult(range[0]);
        return q.getResultList();
    }

    public int count() {
        javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
        javax.persistence.criteria.Root<T> rt = cq.from(entityClass);
        cq.select(getEntityManager().getCriteriaBuilder().count(rt));
        javax.persistence.Query q = getEntityManager().createQuery(cq);
        return ((Long) q.getSingleResult()).intValue();
    }

    public List searchKeyWord(String keyword) {

        Query query = getEntityManager().createNamedQuery("Projects.findByProjectName");
        query.setParameter("projectName",keyword+"%");
        List list = query.getResultList();
        return list;
    }

    public List<T> searchEmployees(String employeeBusinessMail) {
        Query query = getEntityManager().createNamedQuery("Employees.findByBusinessEmail");
        query.setParameter("businessEmail",employeeBusinessMail + "%");
        return query.getResultList();
    }

    public Employees searchEmployee(String employeeBusinessMail) {
        System.out.println("#################Mail: "+employeeBusinessMail);
        Query query = getEntityManager().createNamedQuery("Employees.findByBusinessMail");
        query.setParameter("businessEmail",employeeBusinessMail);
        return (Employees)query.getSingleResult();
    }
    
    
    public List getProjects(int empID, Date dayofWeek) {
        // set the date
        Calendar call = Calendar.getInstance();
        call.setTime(dayofWeek);
        // "calculate" the start date of the week
        Calendar first = (Calendar) call.clone();
        first.add(Calendar.DAY_OF_WEEK, (first.getFirstDayOfWeek()- first.get(Calendar.DAY_OF_WEEK)));
        // and add six days to the end date
        Calendar last = (Calendar) first.clone();
        last.add(Calendar.DAY_OF_YEAR, 6);
        // print the result
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        df.format(last.getTime());
        Date start = first.getTime();
        Date end = last.getTime();       
        Query query = getEntityManager().createNamedQuery("TimeLog.findTimeLogsGroupBy");
        Employees emp=new Employees();
        emp.setEmpId(empID);
        query.setParameter("emplyee",emp);
        query.setParameter("first", start);
        query.setParameter("last", end);
        List li=query.getResultList();
        System.out.println("////////////////Start Date: "+start);
        System.out.println("////////////////End Date: "+end);
        System.out.println("///////////////List: "+li.size());
        return  li;
    }

    public static boolean isWithinDateRange(Date dateToSearch, Date startdate, Date enddate) {
        Calendar calstart = Calendar.getInstance();
        calstart.setTime(startdate);
        calstart.set(Calendar.HOUR, 0);
        calstart.set(Calendar.MINUTE, 0);
        calstart.set(Calendar.SECOND, 0);


        Calendar calend = Calendar.getInstance();
        calend.setTime(enddate);
        calend.set(Calendar.HOUR, 0);
        calend.set(Calendar.MINUTE, 0);
        calend.set(Calendar.SECOND, 0);


        Calendar calsearch = Calendar.getInstance();
        calsearch.setTime(dateToSearch);
        calsearch.set(Calendar.HOUR, 0);
        calsearch.set(Calendar.MINUTE, 0);
        calsearch.set(Calendar.SECOND, 0);


        if (((isDateEqual(calstart.getTime(), calsearch.getTime())) || (calstart.getTime().before(calsearch.getTime())))
                && ((isDateEqual(calend.getTime(), calsearch.getTime())) || (calend.getTime().after(calsearch.getTime())))) {
            return true;
        } else {
            return false;
        }
    }

    public static boolean isDateEqual(Date date1, Date date2) {
        Calendar cal1 = Calendar.getInstance();
        Calendar cal2 = Calendar.getInstance();
        cal1.setTime(date1);
        cal2.setTime(date2);
        if ((cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH)) && (cal1.get(Calendar.DATE) == cal2.get(Calendar.DATE)) && (cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR))) {
            return true;
        } else {
            return false;
        }
    }

    // delete Time log
    public void deleteTimeLog(List<TimeLog> timelog) {
        Iterator<TimeLog> itr = timelog.iterator();
        while (itr.hasNext()) {
            TimeLog dayworked = itr.next();
            Query query = getEntityManager().createNamedQuery("TimeLog.delete");
            query.setParameter("tlId", dayworked.getTlId());
            query.executeUpdate();
        }
    }

    /**
     * Delete Selected Expenses from
     * Database...
     */
    public void deleteExpense(List<Expenses> expenses) {
        System.out.println("############deleteExpense############");
        Iterator<Expenses> itr = expenses.iterator();
        while (itr.hasNext()) {
            Expenses expense = itr.next();
            Query query = getEntityManager().createNamedQuery("Expenses.deleteByExpId");
            query.setParameter("expId", expense.getExpId());
            System.out.println("###########Record to Delete: "+expense.getExpId());
            query.executeUpdate();
        }
    }
    
    public List getTimeLog(int project_id)
    {
          Query query = getEntityManager().createNamedQuery("TimeLog.findByprojectId");
      
          Projects p=new Projects();
          p.setProId(project_id);
          query.setParameter("project", p);
        List list = query.getResultList();
        return list;
    }
    
     public List getExpenses(int project_id)
    {
          Query query = getEntityManager().createNamedQuery("Expenses.findByprojectId");
      
          Projects p=new Projects();
          p.setProId(project_id);
          query.setParameter("project", p);
          query.setParameter("reimbursable", "1");
        List list = query.getResultList();
        return list;
    }
}
